package jmcnet.libcommun.communs.newjmcnetds
{
	import flash.events.EventDispatcher;
	import flash.utils.getQualifiedClassName;
	
	import jmcnet.libcommun.communs.exceptions.ExceptionTechnique;
	import jmcnet.libcommun.communs.structures.HashTable;
	import jmcnet.libcommun.logger.JMCNetLog4JLogger;
	
	import mx.rpc.remoting.RemoteObject;

	/**
	 * La classe de base d'un Delegate (pour utilisation de BlazeDS 4)
	 */
	
	[Event(type="jmcnet.libcommun.communs.newjmcnetds.EventDelegateAppelOK")]
	[Event(type="jmcnet.libcommun.communs.newjmcnetds.EventDelegateAppelKO")]
	public class BaseDelegate extends EventDispatcher
	{
		private static var log:JMCNetLog4JLogger = new JMCNetLog4JLogger(getQualifiedClassName(BaseDelegate)); 
		
		// Un callback d'erreur (pouvant donc être généralisé pour tout le monde)
		private var _defaultErrorCallback:Function=null;
		// Le remote object qui sera appelé
		private var _service:BlazeDSService=null;
		// La liste des méthodes appelables
		private var _lstMethodes:HashTable = new HashTable();
		// Enregitrement a eu lieu
		private var _enregFait:Boolean=false;
		
		public function BaseDelegate(service:BlazeDSService, errorCallback:Function) {
			_service = service;
			_defaultErrorCallback = errorCallback;
		}
		
		/**
		 * Enregistrement de toutes les methodes du delegate
		 */
		protected function enregistrerToutesMethodes():void {
			throw new ExceptionTechnique("La méthode enregistrerToutesMethodes n'est pas implémentée");
		}
		
		/**
		 * Permet d'enregistrer une methode appelable sur ce service
		 * @param onResult doit pointer vers une fonction qui prend un Object en parametre. Cet objet contient la réponse du service,
		 * @param onError doit pointer vers une fonction qui prend un Fault en parametre. Cet objet contient la description de l'erreur.
		 */
		public function enregistrerMethode(nomMethode:String, onResult:Function=null, onError:Function=null):void {
			log.info("Appel enregistrerMethode : nomMethode="+nomMethode+" service="+_service);
			// Si onError est nul, il a du être déclaré par défaut dans le constructeur
			if (onError != null) {
				_lstMethodes.addItem(nomMethode, new Methode(nomMethode, onResult, onError, _service, this));
			}
			else {
				// On met le defaultErrorCallback sinon
				_lstMethodes.addItem(nomMethode, new Methode(nomMethode, onResult, _defaultErrorCallback, _service, this));
			}
			log.info("Fin enregistrerMethode : nomMethode="+nomMethode);
		}
		
		public function appellerMethode(nomMethode:String, ... args:Array):void {
			log.info("Appel appellerMethode nomMethode='"+nomMethode+"' args.length="+args.length+" args="+args);
			
			if (_service == null) {
				log.error("Le service n'est pas initialisé");
				throw new ExceptionTechnique("Impossible d'appeler la méthode '"+nomMethode+"' car le service n'est pas initialisé");
			}
			
			if (!_enregFait) {				
				log.debug("L'enregistrement des méthodes n'est pas fait, on le fait");
				enregistrerToutesMethodes();
				_enregFait = true;
			}
			
			// On rechercher la méthode enregistree
			var methode:Methode=_lstMethodes.getItem(nomMethode);
			if (methode == null) {
				log.error("La méthode '"+nomMethode+"' n'a pas été enregistrée");
				throw new ExceptionTechnique("Impossible d'appeler la méthode '"+nomMethode+"' car elle n'a pas été enregistrée");
			}
			
			methode.appeler(args);
			log.info("Fin appellerMethode '"+nomMethode+"' OK");
		}
		
		public function appellerMethodeAvecCallback(nomMethode:String, onResultCallback:Function, onErrorCallback:Function, ... args:Array):void {
			log.info("Appel appellerMethodeAvecCallback nomMethode='"+nomMethode+"' args.length="+args.length+" args="+args);
			
			if (_service == null) {
				log.error("Le service n'est pas initialisé");
				throw new ExceptionTechnique("Impossible d'appeler la méthode '"+nomMethode+"' car le service n'est pas initialisé");
			}
			
			if (!_enregFait) {				
				log.debug("L'enregistrement des méthodes n'est pas fait, on le fait");
				enregistrerToutesMethodes();
				_enregFait = true;
			}
			
			// On cree une méthode intermediaire
			var methode:Methode = new Methode(nomMethode, onResultCallback, onErrorCallback, _service);
			methode.appeler(args);
			
			log.info("Fin appellerMethodeAvecCallback '"+nomMethode+"' OK");
			
		}
	}
}